import { inputComponents } from "./config"

/**
 * 生成一个永不重复的 key
 * @param { Number } randomLength 
 */
export function getUuiKey(randomLength = 5) {
  return Number(Math.random().toString().substr(2, randomLength) + Date.now()).toString(36)
}

// 给需要添加的控件添加自定义属性,即补充完整属性
export function createFormItem(item,) {
  const config = item.__config__;
  config.formId = `field${getUuiKey()}`; // 表单项id
  config.renderKey = `${config.formId}`; // 改变renderKey后可以实现强制更新组件
  // 根据容器布局类型设置不同的属性
  // colFormItem 非布局组件 rowFormItem 布局型组件
  if (config.layout === "colFormItem") {
    item.__vModel__ = config.formId; // 字段名称
  } else if (config.layout === "rowFormItem") {
    // 布局型组件
    config.componentName = config.formId;
    !Array.isArray(config.children) && (config.children = []);
    delete config.label; // rowFormItem无需配置label属性
  }
  if (Array.isArray(config.children)) {
    config.children = config.children.map((childItem,) =>
      createFormItem(childItem,)
    );
  }

  return item;
}
// 更新修改后的表单列表,list-完整表单，value更新的表单项数据
export function updateForm(list, newValue) {
  const formId = newValue.__config__?.formId;
  const index = list.findIndex(
    item => item.__config__.formId == formId
  );
  if (index > -1) {
    // 在显示列表中找到选中的表单项,将修改后的内容更新在列表中
    list.splice(index, 1, deepClone(newValue));
  }
}
// 根据不同表单项设置不同样式,isBorder-是否存在边框
export function changClass(item, currentData, formConf) {
  const isRowCon = item.__config__.tag == "form-row-container"; // 是否为行容器组件
  return {
    "drawing-item-hover": !isRowCon,
    "drawing-row-item":
      formConf.unFocusedComponentBorder &&
      item.__config__.formId != currentData?.__config__?.formId ||
      isRowCon, // 是否显示未选中组件边框
    "active-from-item":
      item.__config__.formId == currentData?.__config__?.formId &&
      !isRowCon
  };
}

// 1. 根据是否必填添加对应的必填校验（此处为了错误状态的中文显示）
// 2. 将“正则校验”属性中添加的规则中的字符串转为正则表达式（纯字符串无法识别）
export function formRules(item) {
  if (item.disabled || item.readonly) return []
  let ruleList = [];
  // 添加必填的校验文字
  if (item.__config__.required) {
    ruleList.push({ required: true, message: `${item.__config__.label}不能为空` })
  }
  if (item.__config__.regList && item.__config__.regList.length) {
    ruleList = ruleList.concat(formRulesReg(item.__config__.regList))
  }
  return ruleList
}

// 将规则中的字符串转为正则表达式
export function formRulesReg(rules) {
  let ruleList = [];
  rules.forEach(rule => {
    let obj = deepClone(rule);
    let str = rule.pattern;
    if (str[0] == "/" && str[str.length - 1] == "/") {
      str = str.slice(1, str.length - 1);
    }
    // 需要将字符串转为正则字面量，不然无法识别
    obj.pattern = new RegExp(str);
    ruleList.push(obj);
  });
  return ruleList;
}

export function isNumberStr(str) {
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}

// 深拷贝对象
export function deepClone(obj) {
  const _toString = Object.prototype.toString

  // null, undefined, non-object, function
  if (!obj || typeof obj !== 'object') {
    return obj
  }

  // DOM Node
  if (obj.nodeType && 'cloneNode' in obj) {
    return obj.cloneNode(true)
  }

  // Date
  if (_toString.call(obj) === '[object Date]') {
    return new Date(obj.getTime())
  }

  // RegExp
  if (_toString.call(obj) === '[object RegExp]') {
    const flags = []
    if (obj.global) { flags.push('g') }
    if (obj.multiline) { flags.push('m') }
    if (obj.ignoreCase) { flags.push('i') }

    return new RegExp(obj.source, flags.join(''))
  }

  const result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}

  for (const key in obj) {
    result[key] = deepClone(obj[key])
  }

  return result
}

// 将一个对象的每一个属性名都转换为驼峰命名，该对象存在多层嵌套
export function toCamelCase(obj) {
  if (typeof obj === 'object' && obj !== null) {
    let newObj = {};
    if (Array.isArray(obj)) {
      newObj = [];
    }

    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        const camelCaseKey = toCamelCaseString(key);
        newObj[camelCaseKey] = toCamelCase(obj[key]);
      }
    }

    return newObj;
  } else {
    return obj;
  }
}
// 将字符串转换为驼峰命名法（CamelCase）
export function toCamelCaseString(str) {
  return str.replace(/-([a-z])/g, function (g) {
    return g[1].toUpperCase();
  });
}



//  根据id查找对应树结构节点路径  tree：树结构；id： 对应节点；path：每次保存相应路径的节点
export function getPathById(tree, id, props = { text: 'text', value: 'value', children: 'children' }, path) {
  if (!path) {
    path = []
  }
  for (let i = 0; i < tree.length; i++) {
    let tempPath = [...path]
    tempPath.push(tree[i])
    if (tree[i][props.value] === id) {
      return tempPath
    }
    if (tree[i][props.children]) {
      const reuslt = getPathById(tree[i][props.children], id, props, tempPath)
      if (reuslt) {
        return reuslt
      }
    }
  }
}

// 对文件名进行处理，将文件名称和后缀名分割开
export function formatFile(fileName) {
  let file = {
    name: '',
    ext: '', // 后缀名
    typeName: '', // 后缀名类型名称
  }
  const index = fileName?.lastIndexOf('.')
  if (index == -1) {
    file.name = fileName
  } else {
    file.name = fileName.substring(0, index)
    file.ext = fileName.substring(index + 1, fileName.length)
    file.typeName = getFileType(file.ext).name
    file.svg = getFileType(file.ext).svg
  }
  return file
}

// 根据后缀名得到该文件的类型，为文档/图片/音频/视频
export function getFileType(ext) {
  const fileType = [
    {
      name: '文档',
      type: ["doc", "docx"],
      svg: 'word',
    }, {
      name: '表格',
      type: ["xls", "xlsx",],
      svg: 'xlsx'
    }, {
      name: '演示文稿',
      type: ["ppt", "pptx",],
      svg: "ppt",
    }, {
      name: 'pdf',
      type: ["pdf",],
      svg: "pdf",
    }, {
      name: '压缩包',
      type: ["rar", "zip",],
      svg: 'zip'
    },
    {
      name: '图片',
      type: ["jpg", "jpeg", "png", "bmp", "gif"],
      svg: 'png',
    }, {
      name: '视频',
      type: ["mp4", "mov", "wmv", "flv", "avi", "3gp"],
      svg: 'mp4'
    }
  ]
  let type = {
    name: '',
    svg: 'unknow'
  }
  fileType.forEach(el => {
    const index = el.type.findIndex(v => v === ext)
    if (index > -1) {
      type.name = el.name
      type.svg = el.svg
    }
  })

  return type
}
// 遍历树，对树的节点进行操作，该树为数组结构
export function traverseTree(tree, fun) {
  for (let i = 0; i < tree.length; i++) {
    const currentNode = tree[i];
    // 处理当前节点
    if (fun) fun(currentNode)
    // 如果当前节点有子节点，递归遍历子节点
    if (Array.isArray(currentNode.__config__.children) && currentNode.__config__.children.length > 0) {
      traverseTree(currentNode.__config__.children, fun);
    }
  }
}

// 将树结构转为数组
export function treeToArray(tree, children = 'children') {
  let treeData = JSON.parse(JSON.stringify(tree))
  let ary = []
  treeData.forEach(item => {
    if (item[children]) {
      ary.push(item)
      if (item[children].length > 0) {
        ary.push(...treeToArray(item[children], children))
      }
    } else {
      ary.push(item)
    }
    delete item[children]
  })
  return ary
}

// 根据级联的值获取级联的显示文本
export function getCascaderText(formItem) {
  const props = formItem.props.props;
  const formValue = formItem.__config__.defaultValue;
  const options = treeToArray(formItem.options, props.children)
  let path = []
  formValue?.forEach(value => {
    path.push(options.find(item => item[props.value] == value)[props.label])
  })
  // 间隔符
  const separator = formItem.separator;
  // 是否展示全路径
  const showAllLevels = formItem['show-all-levels'];
  return showAllLevels ? path.join(separator) : path[path.length - 1];
}

// 对已填报的表单进行修改，使其可以按照要求显示内容
export function formateForm(list) {
  let data = []
  deepClone(list).forEach(item => {
    let text = item.__config__.defaultValue
    let comName = 'TextShow'
    // 1. 附件
    if (item.__config__.tag == 'form-upload') {
      text = JSON.parse(item.__config__.defaultValue || '[]') // 展示的内容
      comName = 'FilesShow'
    }
    // 图片
    if (item.__config__.tag == 'form-image') {
      text = JSON.parse(item.__config__.defaultValue || '[]') // 展示的内容
      comName = 'ImageShow'
    }
    // 2. 时间区间
    if (['form-daterange-picker', 'form-timerange-picker'].includes(item.__config__.tag)
      && Array.isArray(item.__config__.defaultValue)) {
      text = `${item.__config__.defaultValue[0]} ${item["range-separator"]} ${item.__config__.defaultValue[1]}`
    }
    // 3. 多选框组/单选框组/下拉选择
    if (['form-select', 'form-radio-group', 'form-checkbox-group'].includes(item.__config__.tag)) {
      const options = item.__slot__.options
      const defaultValue = item.__config__.defaultValue
      if (Array.isArray(defaultValue)) {
        text = options.filter(item => defaultValue.includes(item.value)).map(item => item.label).join("，")
      } else {
        text = options.find(item => item.value == defaultValue)?.label

      }
    }

    // 4. 富文本
    if (item.__config__.tag == 'form-rich-text') {
      comName = 'RichTextShow'
    }

    // 5. 级联
    if (item.__config__.tag == 'form-cascader') {
      text = getCascaderText(item)
    }

    // 6. 行容器
    if (item.__config__.tag == 'form-row-container') {
      comName = 'RowContainerShow'

    }
    // 7. 人员选择
    if (item.__config__.tag == 'form-user-picker') {
      comName = 'NameShow'
      text = JSON.parse(item.__config__.defaultValue || '[]') // 展示的内容
    }
    // 8. 评分
    if (item.__config__.tag == 'form-rate') {
      comName = 'form-rate'
      item.readonly = true
      item.__config__.required = false
    }
    // 9. 签字板
    if (item.__config__.tag == 'form-signature') {
      // comName = 'form-signature'
      // item.onlyShow = true
      comName = 'SignShow'
    }
    data.push({ ...item, text, comName })

  })

  return data
}

export function formTreeToArray(tree) {
  let treeData = deepClone(tree);
  let ary = [];
  treeData.forEach((item) => {
    if (item.__config__.children) {
      ary.push(item);
      if (item.__config__.children.length > 0) {
        ary.push(...formTreeToArray(item.__config__.children));
      }
    } else {
      ary.push(item);
    }
  });
  return ary;
}

// 表单校验
export function validateForm(data) {
  let errorMsg = [] // 用于存储错误提示
  // 1. 平铺表单，去除行容器
  const list = formTreeToArray(data)
  // 2. 存储所有表单标题 
  // const labels = list.map(item => item.__config__.label)
  list.forEach(item => {
    if (item.__config__.tag === 'form-row-container') {
      if (!item.__config__.children.length) {
        errorMsg.push(`行容器内未添加组件`)
      }
    } else {
      const label = item.__config__.label
      // 3-1. 校验标题不能为空
      if (!label) {
        const name = inputComponents.find(itemm => itemm.__config__.tag === item.__config__.tag)?.__config__?.label
        errorMsg.push(`${name}标题不能为空`)
      }
      // 3-2. 表单名称不允许重复
      const labels = list.filter(itemm => itemm.__config__.label === label)
      if (label && labels.length > 1) {
        errorMsg.push(`${label}标题名称重复`)
      }
      // 3.3 多选、单选、下拉选框、级联选择器选项不能为空
      const options = item.__slot__?.options || item.options || null
      if (options && options.length === 0) {
        errorMsg.push(`${label}未设置选项`)
      }

    }

  })
  errorMsg = [...new Set(errorMsg)]

  if (errorMsg.length) {
    return { valid: false, errorMsg }
  }
  return { valid: true, errorMsg }
}

// 根据 keyName 求两个数组的交集，keyName为数组内对象的属性名称
export function intersectionFun(arr1, arr2, keyName = 'value') {
  const arr3 = arr1.map(item => item[keyName])
  const arr4 = arr2.filter(x => new Set(arr3).has(x[keyName]))
  return arr4
}

// 根据 keyName 求两个数组的差集，keyName为数组内对象的属性名称
export function differenceSetFun(arr1, arr2, keyName = 'value') {
  let arr3 = arr1.filter(v => {
    return arr2.every(e => e[keyName] != v[keyName]);
  });
  return arr3
}

// 根据 keyName 求两个数组的并集，keyName为数组内对象的属性名称
export function unionFun(arr1, arr2, keyName = 'value') {
  let arr3 = arr1.concat(arr2)
  let obj = []
  let result = arr3.reduce((prev, cur) => {
    obj[cur[keyName]] ? '' : obj[cur[keyName]] = true && prev.push(cur)
    return prev
  }, [])
  return result
}

// 根据key和value将值填入到表单当中
export function setFormValue(list, form) {
  list.forEach(item => {
    if (form && form[item.__config__.formId]) {
      item.__config__.defaultValue = form[item.__config__.formId]
    }
    if (item.__config__.children && item.__config__.children.length) {
      item.__config__.children = setFormValue(item.__config__.children, form)
    }
  })
  return list
}
// 转base64码
export function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    let fileResult = "";
    reader.readAsDataURL(file);
    // 开始转
    reader.onload = () => {
      fileResult = reader.result;
    };
    // 转 失败
    reader.onerror = (error) => {
      reject(error);
    };
    // 转 结束
    reader.onloadend = () => {
      resolve(fileResult);
    };
  });
}